#include <iostream>
#include <cstring>
#include <cmath>
using namespace std;

const int N = 12;

int a, b;   //获取输入
int num[N]; //将某个数拆分开成数组，方便计算

int get(int l, int r) //从num数组的l和r中（包括l和r）取数并且组成一个整数返回
{
    int n = 0;
    for (int i = l; i <= r; ++i)
        n = n * 10 + num[i];
    return n;
}

int inget(int n) //get的逆操作，将某个数拆分后存入数组
{
    memset(num, 0, sizeof 0); //这里还是保险起见加个初始化
    int k = 0;                //记录n的位数
    while (n)
    {
        num[++k] = n % 10; //注意，这么整出来是倒序的
        n /= 10;
    }
    for (int i = 1; i <= k / 2; ++i) //这里是把数组倒过来一下
        swap(num[i], num[k - i + 1]);
    return k;
}

int count(int n, int k) //返回从1~n中k出现的次数
{
    n = inget(n);                     //拆分n，并且这里重复利用n来记录长度
    int res = 0;                      //记录最终的结果
    for (int i = 1 + !k; i <= n; ++i) //开始假设这个数处于n的哪一位，从高位开始。这里加的!k主要是为了防止k为0，k为0的时候不可能处于最高位
    {
        res += get(1, i - 1) * pow(10, n - i); //情况1，不论这个数是啥，这个是最基本的，也就是前面的是0~abc-1后面的是0~999（这里是拿abcdefg举例，求得是d）
        if (!k)                                //还是老生常谈的前置0的问题，这里如果我们数的数是0的话，那么我们前面就不能是0~abc-1，而是1~abc-1所以要减去一个0~999
            res -= pow(10, n - i);             //为了处理特殊情况3，特殊情况1和2都是无所谓的，会因为get函数和pow函数的性质去掉
        if (num[i] == k)                       //如果我们找的情况正好是如题解中的2.2
            res += get(i + 1, n) + 1;          //既0~efg
        else if (num[i] > k)                   //这里是情况2.3
            res += pow(10, n - i);
        //其实这里应该还有一个加0的，也就是情况2.1，但是这里省略了
    }
    return res;
}

int main()
{
    freopen("cin.txt", "r", stdin);
    while (cin >> a >> b, a || b)
    {
        if (a > b)      //如果前面的比后面的大
            swap(a, b); //那就交换一波
        for (int i = 0; i < 10; ++i)
            cout << count(b, i) - count(a - 1, i) << " ";
        puts("");
    }
    return 0;
}